package com.czk.stream;

import java.util.*;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author:ChenZhangKun
 * @Date: 2023/10/9 20:28
 */
public class CollectorGroup {

    public static void main(String[] args) {
        List<Student> students = Stream.of(new Student("陈彰坤", 29, "三班", "数学", 100)
        ,new Student("陈彰杰·", 31, "二班", "语文", 90)
        ,new Student("陈沐宁", 1, "一班", "外语", 100)
        ,new Student("宁沐莀", 1, "四班", "物理", 100)
        ,new Student("宁中琼", 28, "五班", "化学", 80)
        ,new Student("张洪碧", 50, "六班", "生物", 70)
        ,new Student("宁升华", 52, "六班", "地理", 60)).collect(Collectors.toList());

        // 1  拼接键
        Map<Integer, List<Student>> collect = students.stream().collect(Collectors.groupingBy(student -> student.getScore() + 10));
        System.out.println(collect);
        // 2 对建进行条件判断 学生划分及格不及格两类
        Map<Boolean, List<Student>> collect1 = students.stream().collect(Collectors.groupingBy(student -> student.getScore() > 80));
        System.out.println(collect1);
        // 3 根据多级范围 根据学生成绩来评分
        Map<String, List<Student>> collect2 = students.stream().collect(Collectors.groupingBy(student -> {
            if (student.getScore() < 60) {
                return "E";
            } else if (student.getScore() < 70) {
                return "D";
            } else if (student.getScore() < 80) {
                return "C";
            } else if (student.getScore() < 90) {
                return "B";
            } else {
                return "A";
            }
        }));
        System.out.println(collect2);
        // 计数
        Map<Integer, Long> collect3 = students.stream().collect(Collectors.groupingBy(Student::getScore, Collectors.counting()));
        System.out.println(collect3);
        // 求和
        Map<String, Integer> collect4 = students.stream().collect(Collectors.groupingBy(Student::getClazz, Collectors.summingInt(Student::getScore)));
        System.out.println(collect4);
        // 平均值
        Map<String, Double> collect5 = students.stream().collect(Collectors.groupingBy(Student::getClazz, Collectors.averagingDouble(Student::getScore)));
        System.out.println(collect5);
        // 同组最小值
        Map<String, Optional<Student>> collect6 = students.stream().collect(Collectors.groupingBy(Student::getClazz, Collectors.minBy(Comparator.comparing(Student::getScore,(v1,v2)->v1))));
        System.out.println(collect6);
        // 同组最大值
        Map<String, Optional<Student>> collect7 = students.stream().collect(Collectors.groupingBy(Student::getClazz, Collectors.maxBy(Comparator.comparing(Student::getScore,(v1,v2)->v1))));
        System.out.println(collect7);
        // 完整统计（同时获取以上的全部统计结果）
        HashMap<String, DoubleSummaryStatistics> collect8 = students.stream().collect(Collectors.groupingBy(Student::getClazz, HashMap::new, Collectors.summarizingDouble(Student::getScore)));
        collect8.forEach((key,value)->{
            System.out.println(value.getMax());
            System.out.println(value.getMin());
            System.out.println(value.getAverage());
            System.out.println(value.getCount());
            System.out.println(value.getSum());
        });
        // 切分结果，同时统计大于60和小于60分的人的信息
        Map<String, Map<Boolean, List<Student>>> collect9 = students.stream().collect(Collectors.groupingBy(Student::getCourse, Collectors.partitioningBy(student -> student.getScore() > 60)));
        System.out.println(collect9);
        // 多次切分
        Map<String, Map<Boolean, Map<Boolean, List<Student>>>> collect10 = students.stream().collect(Collectors.groupingBy(Student::getClazz, Collectors.partitioningBy(student -> student.getScore() > 60, Collectors.partitioningBy(student -> student.getScore() > 90))));
        System.out.println(collect10);
        // 合并结果，计算每科总分
        Map<String, Integer> collect11 = students.stream().collect(Collectors.groupingBy(Student::getCourse, Collectors.reducing(0, Student::getScore, Integer::sum)));
        System.out.println(collect11);
        // 合并结果，获取每科最高分的学生信息
        Map<String, Optional<Student>> collect12 = students.stream().collect(Collectors.groupingBy(Student::getCourse, Collectors.reducing(BinaryOperator.maxBy(Comparator.comparing(Student::getScore)))));
        System.out.println(collect12);
        // 统计各班姓名合并为字符串
        Map<String, String> collect13 = students.stream().collect(Collectors.groupingBy(Student::getClazz, Collectors.mapping(Student::getName, Collectors.joining(","))));
        System.out.println(collect13);
        // 映射结果
        Map<String, Map<String, Integer>> collect14 = students.stream().collect(Collectors.groupingBy(Student::getCourse, Collectors.toMap(Student::getName, Student::getScore)));
        System.out.println(collect14);
        // 映射结果为指定类型的map
        Map<String, LinkedHashMap<String, Integer>> collect15 = students.stream().collect(Collectors.groupingBy(Student::getCourse, Collectors.toMap(Student::getName, Student::getScore, (k1, k2) -> k1, LinkedHashMap::new)));
        System.out.println(collect15);
        //
        Map<String, List<String>> collect16 = students.stream().collect(Collectors.groupingBy(Student::getClazz, Collectors.mapping(Student::getName, Collectors.toList())));
        System.out.println(collect16);



        Map<String, String> groupMapperThenLink = students.stream()
                .collect(Collectors.groupingBy(Student::getCourse,
                        Collectors.collectingAndThen(Collectors.mapping(Student::getName, Collectors.joining("，")), s -> "学生名单：" + s)));
        System.out.println(groupMapperThenLink);

    }
    public static class Student{
        private String name;
        private int age;
        private String clazz;
        private String course;
        private int score;

        public Student(String name, int age, String clazz, String course, int score) {
            this.name = name;
            this.age = age;
            this.clazz = clazz;
            this.course = course;
            this.score = score;
        }

        public Student() {
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }

        public String getClazz() {
            return clazz;
        }

        public String getCourse() {
            return course;
        }

        public int getScore() {
            return score;
        }

        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", clazz='" + clazz + '\'' +
                    ", course='" + course + '\'' +
                    ", score=" + score +
                    '}';
        }
    }
}
